﻿\subsection{Поиск минимального и максимального значения}

\subsubsection{32-bit}

\lstinputlisting[style=customc]{patterns/07_jcc/minmax/minmax.c}

\lstinputlisting[caption=\NonOptimizing MSVC 2013,style=customasmx86]{patterns/07_jcc/minmax/minmax_MSVC_2013_RU.asm}

\myindex{x86!\Instructions!Jcc}
Эти две функции отличаются друг от друга только инструкцией условного перехода:
\INS{JGE} (\q{Jump if Greater or Equal}~--- переход если больше или равно) используется в первой
и \INS{JLE} (\q{Jump if Less or Equal}~--- переход если меньше или равно) во второй.

\myindex{\CompilerAnomaly}
\label{MSVC_double_JMP_anomaly}
Здесь есть ненужная инструкция \JMP в каждой функции, которую MSVC, наверное, оставил по ошибке.

\myparagraph{Без переходов}

ARM в режиме Thumb напоминает нам x86-код:

\lstinputlisting[caption=\OptimizingKeilVI (\ThumbMode),style=customasmARM]{patterns/07_jcc/minmax/minmax_Keil_Thumb_O3_RU.s}

\myindex{ARM!\Instructions!Bcc}
Функции отличаются только инструкцией перехода: \INS{BGT} и \INS{BLT}.
А в режиме ARM можно использовать условные суффиксы, так что код более плотный.
\INS{MOVcc} будет исполнена только если условие верно:

\myindex{ARM!\Instructions!MOVcc}

\lstinputlisting[caption=\OptimizingKeilVI (\ARMMode),style=customasmARM]{patterns/07_jcc/minmax/minmax_Keil_ARM_O3_RU.s}

\myindex{x86!\Instructions!CMOVcc}
\Optimizing GCC 4.8.1 и оптимизирующий MSVC 2013 
могут использовать инструкцию \INS{CMOVcc}, которая аналогична \INS{MOVcc} в ARM:

\lstinputlisting[caption=\Optimizing MSVC 2013,style=customasmx86]{patterns/07_jcc/minmax/minmax_GCC481_O3_RU.s}

\subsubsection{64-bit}

\lstinputlisting[style=customc]{patterns/07_jcc/minmax/minmax64.c}

Тут есть ненужные перетасовки значений, но код в целом понятен:

\lstinputlisting[caption=\NonOptimizing GCC 4.9.1 ARM64,style=customasmARM]{patterns/07_jcc/minmax/minmax64_GCC_49_ARM64_O0.s}

\myparagraph{Без переходов}

Нет нужды загружать аргументы функции из стека, они уже в регистрах:

\lstinputlisting[caption=\Optimizing GCC 4.9.1 x64,style=customasmx86]{patterns/07_jcc/minmax/minmax64_GCC_49_x64_O3_RU.s}

MSVC 2013 делает то же самое.

\myindex{ARM!\Instructions!CSEL}
В ARM64 есть инструкция \INS{CSEL}, которая работает точно также, как и \INS{MOVcc} в ARM и \INS{CMOVcc} в x86,
но название другое: \q{Conditional SELect}.

\lstinputlisting[caption=\Optimizing GCC 4.9.1 ARM64,style=customasmARM]{patterns/07_jcc/minmax/minmax64_GCC_49_ARM64_O3_RU.s}

\subsubsection{MIPS}

А GCC 4.4.5 для MIPS не так хорош, к сожалению:

\lstinputlisting[caption=\Optimizing GCC 4.4.5 (IDA),style=customasmMIPS]{patterns/07_jcc/minmax/minmax_MIPS_O3_IDA_RU.lst}

Не забывайте о \IT{branch delay slots}: первая \INS{MOVE} исполняется \IT{перед} \INS{BEQZ},
вторая \INS{MOVE} исполняется только если переход не произошел.

